export default class TaskManager {
    private tasks: Array<any>;
    private excuteByBatch: boolean;
    //当前正在处理的任务批次号，从0开始，每执行完一个批次的任务，这个数加1
    private currentBatch: number;
    //当前正在处理批次的任务的优先级，由外部设置
    private currentPriority: number;
    private queues: Array<any>;
    public isRunning: boolean;

    constructor(options: any) {
        this.tasks = [];
        this.queues = [];
        if (options.excuteByBatch) {
            this.excuteByBatch = options.excuteByBatch;
        }
        else {
            this.excuteByBatch = false;
        }
        this.currentBatch = 0;
        this.currentPriority = 0;
        this.isRunning = false;
    }

    //向任务管理器中添加任务，但不会执行
    public add(task: any) {
        if (!this.isRunning) {
            if (!task.priority || task.priority < 0) {
                task.priority = 0
            }

            if (!task.asyn)
                task.asyn = false;

            task.status = 'pending';
            this.tasks.push(task);
        }
        else {
            console.warn('TaskManager:add; You can not add a new task while the manager is in progress!');
        }
    }

    //执行任务管理器中所有任务，一旦开始执行，则不能中途添加任务
    public run() {
        this.isRunning = true;
        if (this.tasks.length < 1) {
            this.isRunning = false;
            return;
        }

        this.tasks.sort(function (a, b) {
            return a.priority - b.priority;
        });

        //将任务按照优先级加入批次队列
        this.queues.push({
            tasks: [this.tasks[0]],
            priority: this.tasks[0].priority,
        })
        for (var i = 1; i < this.tasks.length; i++) {
            let task = this.tasks[i];
            if (task.priority == this.queues[this.queues.length - 1].priority) {
                this.queues[this.queues.length - 1].tasks.push(this.tasks[i]);
            }
            else {
                this.queues.push({
                    tasks: [this.tasks[i]],
                    priority: this.tasks[i].priority,
                });
            }
        }

        if (!this.excuteByBatch) {
            this.excute();
        } else {
            this.batchExcute(0);
        }

    }

    //分批次执行任务，高优先级的任务未执行完毕的情况下不会执行低优先级的任务，异步任务执行回调函数后才认为任务执行完毕
    private batchExcute(batch: number) {
        let _this = this;
        if (batch >= this.queues.length) {
            this.finish();
            return;
        }

        //console.log(batch);
        let queue = this.queues[batch];
        for (let j = 0; j < queue.tasks.length; j++) {
            let task = queue.tasks[j];

            if (!_this.isRunning)
                return;

            this.currentPriority = queue.priority;
            this.currentBatch = j;
            if (!task.asyn) {
                task.excute();
                task.status = 'finished';
                if (!queue.tasks.some(function (t) { return t.status == 'pending'; })) {
                    _this.batchExcute(++batch);
                }
            } else {
                task.complete = function () {
                    task.status = 'finished';

                    if (!_this.isRunning)
                        return false;
                    if (!queue.tasks.some(function (t) { return t.status == 'pending'; })) {
                        _this.batchExcute(++batch);
                    }
                    return true;
                }

                task.excute();
            }
        }
    }

    //不分批次执行任务，也不考虑异步任务
    private excute() {
        for (let i = 0; i < this.queues.length; i++) {
            let queue = this.queues[i];
            this.currentBatch = i;
            this.currentPriority = queue.priority;
            for (let j = 0; j < queue.tasks.length; j++) {
                let task = queue.tasks[j];
                if (!this.isRunning)
                    return;
                task.excute();
                task.status = 'finished';
            }
        }

        this.finish();
    }

    private finish() {
        this.isRunning = false;
        this.tasks = null;
        this.queues = null;
    }

    //中断未执行完毕的任务，包括已提交但未执行回调的异步任务，中断后，异步任务的回调函数不再执行。 (目前不支持暂停操作)
    public abort() {
        // if (!this.isRunning) {
        //     console.warn('TaskManager:abort; The manager is not running!');
        //     return;
        // }
        this.isRunning = false;
        this.tasks = null;
        this.queues = null;
    }

    //获取任务管理器的状态，可以知道当前正在执行哪个优先级的批次
    public getState() {
        return {
            isRunning: this.isRunning,
            batch: this.currentBatch,
            priority: this.currentPriority,
        }
    }

    public getFinishedTasks() {
        return this.tasks.filter(function (t) {
            return t.status == 'finished';
        })
    }

    //根据任务ID查询任务状态
    public getTaskStatus(id: string) {
        if (!this.tasks || this.tasks.length < 1)
            return null;
        for (let i = 0; i < this.tasks.length; i++) {
            if (this.tasks[i].id == id)
                return this.tasks[i].status;
        }

        return null;
    }
}